package admin

import (
	"context"
	"fmt"
	"gateway/core"
	"gateway/util"
	"io/ioutil"
	"net/http"
	"net/url"
	"runtime"
	"strings"
)

type WebServer struct {
	Port          int
	ServerHandler ServerHandler
}

type ServerHandler interface {
	DoGet(context context.Context, path string, params map[string][]string) interface{}
	DoPost(context context.Context, path string, body []byte) interface{}
}

func (server WebServer) Start() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	fmt.Println("listening .....:", server.Port)
	http.ListenAndServe(fmt.Sprintf(":%d", server.Port), &server)
}

func (server WebServer) Stop() {

}

func (server WebServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	path, para := prepareQueryString(req.URL)

	fmt.Println(path, para)

	if req.Method == "POST" {
		if req.Body == nil {
			http.Error(w, "empty body", http.StatusBadRequest)
			return
		}
	}

	ctx := context.WithValue(context.Background(), "headers", req.Header)

	if req.Method == "GET" {
		res := server.ServerHandler.DoGet(ctx, path, para)
		var response = core.Response{
			Errno:  0,
			Errmsg: "success",
			Data:   res,
		}
		w.Write([]byte(util.StructToJson(response)))
	} else if req.Method == "POST" {
		body, err := ioutil.ReadAll(req.Body)
		if err != nil {
			http.Error(w, "cannot read body", http.StatusBadRequest)
			return
		}
		res := server.ServerHandler.DoPost(ctx, path, body)
		var response = core.Response{
			Errno:  0,
			Errmsg: "success",
			Data:   res,
		}
		w.Write([]byte(util.StructToJson(response)))
	}
}

func prepareQueryString(route *url.URL) (string, map[string][]string) {

	if route == nil {

	}

	rawQuery, err := url.QueryUnescape(route.RawQuery)

	if err != nil {
		//panic(NewError("rawQuery parse err"))
	}

	var params = make(map[string][]string)

	values, err := url.ParseQuery(rawQuery)
	if err != nil {
		//panic(NewError(err.Error()))
	}
	for key, value := range values {
		params[key] = value
	}

	return strings.ToLower(route.Path), params
}
